<?php

namespace app\qsapi\service;

use app\qsapi\model\BoxAdole;
use app\qsapi\model\BoxAgreement;
use app\qsapi\model\BoxApp;
use app\qsapi\model\BoxAppVersion;
use app\qsapi\model\BoxNotify;
use app\qsapi\model\Member;
use Exception;
use think\facade\Env;
use VicWord\VicWord;
use think\cache\driver\Redis;
use QCloud\COSSTS\Sts;

class BaseService
{

    protected $version = '';
    protected $platform = '';
    protected $packname = '';
    protected $promoteid = '';
    protected $devicename = '';
    protected $plate = '';
    protected $harmonyos = '';

    // 设备类型,平台内容根据当前值做判定
    protected $device = [
        'ios'       => 1,
        'android'   => 2,
        'pc'        => 3,
        'harmonyos' => 4,
    ];

    // 广告相关设备类型
    protected $adDevice = [
        'android'   => 2,
        'ios'       => 3,
        'pad'       => 4,
        'ipad'      => 5,
        'pc'        => 6,
        'harmonyos' => 7,
    ];

    //板块场景
    protected $plateScene = [
        'all'       => 1, //三端互通
        'pc'        => 2, //pc端
        'android'   => 3, //安卓端
        'ios'       => 4, //ios端
        'harmonyos' => 5  //鸿蒙OS
    ];

    public function __construct()
    {
//        header("Access-Control-Allow-Origin:*");
//        header('Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS,PATCH');
//        header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization,Version,Platform,Packname");
        $this->setVersion((\request()->header()['version'] ?? ''));
        $this->setPlatform((\request()->header()['platform'] ?? ''));
        $this->setPackname(\request()->header()['packname'] ?? '');
        $this->setPromoteId(\request()->header()['promoteid'] ?? '');
        $this->setDeviceName(\request()->header()['devicename'] ?? '');
        $this->setPlate(\request()->header()['plate'] ?? '');

    }

    /**
     * Desc : 设置板块场景
     * User : Steven
     * Date : 2024-08-29 09:34
     * @param $plate
     */
    public function setPlate($plate)
    {
        if (empty($plate)) {
            $plate = request()->get('plate');
        }
        $this->plate = $plate;
    }

    /**
     * Desc : 获取header板块场景
     * User : Steven
     * Date : 2024-08-29 09:35
     * @return string
     */
    public function getPlate(): string
    {
        return $this->plate ?? '';
    }

    /**
     * @param string $platform
     */
    public function setPlatform(string $platform)
    {
        if (empty($platform)) {
            $platform = request()->get('platform');
        }
        if ($platform == 'harmonyos') {
            $this->harmonyos = $platform;
            $platform = 'android';
        }
        $this->platform = $platform;
    }

    /**
     * @param string $version
     */
    public function setVersion(string $version)
    {
        if (empty($version)) {
            $version = request()->get('version');
        }
        $this->version = $version;
    }

    /**
     * @return string
     */
    public function getPlatform()
    {
        return $this->platform;
    }

    /**
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * @param mixed|string $packname
     */
    public function setPackname($packname)
    {
        if (empty($packname)) {
            $packname = request()->get('packname');
        }
        $this->packname = $packname;
    }

    /**
     * @return mixed|string
     */
    public function getPackname()
    {
        return $this->packname;
    }

    /**
     * @param mixed|string $promoteid
     */
    public function setPromoteId($promoteid)
    {
        if (empty($promoteid)) {
            $promoteid = request()->get('promoteid');
        }
        if (intval($promoteid) < 28) {
            $promoteid = '';
        }
        $this->promoteid = $promoteid;
    }

    /**
     * @return mixed|string
     */
    public function getPromoteId()
    {
        return $this->promoteid;
    }

    /**
     * 设置设备名称
     * @param mixed|string $devicename
     */
    public function setDeviceName($deviceName)
    {
        if (empty($devicename)) {
            $deviceName = request()->get('devicename') ?? '';
        }
        $this->devicename = $deviceName;
    }

    /**
     * 获取设备名称
     * @return string
     */
    public function getDeviceName(): string
    {
        return $this->devicename;
    }

    /**
     * 获取最新系统
     * @return array
     */
    public function getNewLastVersion(): array
    {
        $device = ['android' => 1, 'ios' => 2];
        //不在更新渠道里
        if (empty($this->packname)) {
            return api_message([], '包名不能为空!');
        }
        if (empty($this->version)) {
            return api_message([], '版本号不能为空!');
        }
        if (!in_array($this->platform, array_keys($device))) {
            return api_message([], '设备类型错误!');
        }
        $type = $device[$this->platform];
        $appModel = new BoxApp();
        $app_info = $appModel->where(($type == 2 ? 'ios_pack_name' : 'pack_name'), $this->packname)->where('mark', 1)->find();
        if (!$app_info) {
            return api_message();
        }
        //获取当前平台  当前包的最新版本信息
        $where[] = ['mark', '=', 1];
        $where[] = ['app_id', '=', $app_info['id']];
        $where[] = ['type', '=', $type];
        $where[] = ['status', '=', 1];
        $where[] = ['update_date', '<=', now()];
        $appVersionModel = new BoxAppVersion();

        $version_info = $appVersionModel->where($where)->order('code desc')->find();
        if (!$version_info) return api_message();
        //根据range中的1,2,3 比较版本号
        $range_version = $version_info['range_version'];
        $return_info = [];
        switch ($version_info['range']) {
            case 1:
                if (version_compare($this->version, $range_version, '=')) {
                    $return_info['versionCode'] = $version_info['version'];
                    $return_info['versionName'] = 'v' . $version_info['version'];
                }
                break;
            case 2:
                if (version_compare($this->version, $range_version, '<=')) {
                    $return_info['versionCode'] = $version_info['version'];
                    $return_info['versionName'] = 'v' . $version_info['version'];
                }
                break;
        }
        if (empty($return_info)) return api_message([], '暂无更新');
        $return_type = [
            1 => 'silent',//静默更新
            2 => 'solicit',// 弹窗确认更新
            3 => 'forcibly'//强更新
        ];
        $return_info['versionInfo'] = $version_info['content'];
        $return_info['updateType'] = $return_type[$version_info['update_type']] ?? 'silent';
        $return_info['downloadUrl'] = imageUrl($version_info['url']);
        return api_message($return_info ?? []);
    }


    /**
     * 用户协议
     * @return array
     */
    public function getAgreement(): array
    {
        //用户协议
        $data['user_agreement'] = Env::get('domain.image_url') . '/html/user_agreement.html';
        //隐私协议
        $data['privacy_agreement'] = Env::get('domain.image_url') . '/html/privacy_agreement.html';
        //注销协议
        $data['disappear'] = Env::get('domain.image_url') . '/html/disappear.html';
        //千年盒子PC端的注销协议
        $data['cancellation_agreement'] = Env::get('domain.image_url') . '/html/cancellation_agreement.html';
        //千年盒子PC端的儿童协议
        $data['children_agreement'] = Env::get('domain.image_url') . '/html/children_agreement.html';
        return api_message($data);
    }

    /**
     * 用户协议
     * @return array
     */
    public function getAgreementText()
    {

        $where[] = ['mark', '=', 1];
        $where[] = ['status', '=', 1];
        $adole = new BoxAgreement();
        $list = $adole->where($where)->field('id,type,title,content')->select();
        $list = $list ? array_column($list->toArray(), null, 'type') : [];
        return api_message($list);
    }

    /**
     * 用户协议详情
     * @return array
     */
    public function getAgreementTextInfo($type)
    {

        $where[] = ['mark', '=', 1];
        $where[] = ['status', '=', 1];
        $where[] = ['type', '=', $type];
        $adole = new BoxAgreement();
        $info = $adole->where($where)->field('id,type,title,content')->find();
        return $info;
    }

    /**
     * 青少年弹窗
     * @return array
     */
    public function getAdole()
    {
        $where[] = ['mark', '=', 1];
        $where[] = ['status', '=', 1];
        $adole = new BoxAdole();
        $info = $adole->where($where)->field('id,title,content,description')->find();
        $info = $info ? $info->toArray() : [];
        return api_message($info);
    }

    /**
     * 判断昵称是否包含敏感词
     */

    public static function checkSensitive($word, $userId)
    {
        //判断当前用户是否为盒子用户
        $count = Member::where(['id' => $userId, 'status' => 1, 'log_off' => 0])->count();
        if ($count <= 0) {
            return false;
        }
        $vicWord = new VicWord();
        $result = $vicWord->getAutoWord($word);
        $sensitiveWord = array();
        foreach ($result as $item) {
            if ($item[3] === 1) {
                $sensitiveWord[] = $item[0];
            }
        }
        return $sensitiveWord;

    }

    /**
     * 系统公告
     * @return array
     */
    public function getSystemNotice()
    {
        $model = new BoxNotify();
        $where[] = ['mark', '=', 1];
        $where[] = ['status', '=', 1];
        $where[] = ['release_time', '<=', date('Y-m-d H:i:s')];
        $where[] = ['start_time', '<=', time()];
        $where[] = ['end_time', '>=', time()];
        $list = $model->where($where)->field('id,notice_name,content,notes')->select();
        $list = $list ? $list->toArray() : [];
        return api_message($list);
    }

    /**
     * Desc : 接口防抖
     * User : Steven
     * Date : 2024-09-07 17:37
     */
    public function apiAntiShake($key, $memberId): bool
    {
        $redis = new Redis(getRedisConfig());
        $key = "api_anti_shake:{$key}:{$memberId}";
        if ($redis->exists($key)) {
            return false;
        }
        $redis->set($key, 1, 3);
        return true;
    }

    public static function upload_file_tencent_cos($srcPath, $dir = 'admin'): array
    {
        require_once VENDOR_PATH . 'tencent-php/vendor/autoload.php';
        require_once VENDOR_PATH . 'tencent-php/src/Client.php';
        require_once VENDOR_PATH . 'tencent-php/src/Exception/CosException.php';
        // SECRETID 和 SECRETKEY 请登录访问管理控制台进行查看和管理
        $secretId = config('cos.cos_storage.secretId'); //用户的 SecretId，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
        $secretKey = config('cos.cos_storage.secretKey'); //用户的 SecretKey，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
        $region = config('cos.cos_storage.region'); //用户的 region，已创建桶归属的 region 可以在控制台查看，https://console.cloud.tencent.com/cos5/bucket
        $cosClient = new \Qcloud\Cos\Client(
            [
                'region'      => $region,
                'scheme'      => 'http', //协议头部，默认为 http
                'credentials' => [
                    'secretId'  => $secretId,
                    'secretKey' => $secretKey
                ]
            ]
        );
        $result = [];
        ### 上传文件流
        try {
            $bucket = config('cos.cos_storage.bucket'); //存储桶名称 格式：BucketName-APPID
//            $key = generateCode(10); //此处的 key 为对象键，对象键是对象在存储桶中的唯一标识
            $key = $dir . '/' . date('Ymd') . '/' . generateCode(10) . '.' . pathinfo($srcPath, PATHINFO_EXTENSION); //此处的 key 为对象键，对象键是对象在存储桶中的唯一标识
            //$srcPath = "path/to/localFile";//本地文件绝对路径
            $file = fopen($srcPath, "rb");
            if ($file) {
                $result = $cosClient->putObject(
                    [
                        'Bucket' => $bucket,
                        'Key'    => $key,
                        'Body'   => $file
                    ]
                );

            }
        } catch (Exception $e) {
            return api_message([], '上传失败:' . $e->getMessage(), 400);
        }
        unlink($srcPath);
        return api_message(['url' => env('domain.image_url') . $key ?? 'https://' . $result['Location']]);
    }

    /**
     * Notes: 腾讯云上传的临时秘钥
     * User: liubaoqiang
     * DateTime: 2024/12/20 17:44
     * @throws Exception
     */
    public static function cosTempKey(): array
    {
        $redis = new Redis(getRedisConfig());
        $key = 'cos_temp_key';
        $data = $redis->get($key);
        if ($data) return api_message(json_decode($data, true));
        $sts = new Sts();
        $config = array(
            'url'             => 'https://sts.tencentcloudapi.com/', // url和domain保持一致
            'domain'          => 'sts.tencentcloudapi.com', // 域名，非必须，默认为 sts.tencentcloudapi.com
            'proxy'           => '',
            'secretId'        => config('cos.cos_storage.secretId'), // 固定密钥,若为明文密钥，请直接以'xxx'形式填入，不要填写到getenv()函数中
            'secretKey'       => config('cos.cos_storage.secretKey'), // 固定密钥,若为明文密钥，请直接以'xxx'形式填入，不要填写到getenv()函数中
            'bucket'          => config('cos.cos_storage.bucket'), // 换成你的 bucket
            'region'          => config('cos.cos_storage.region'), // 换成 bucket 所在园区
            'durationSeconds' => 1800, // 密钥有效期
            'allowPrefix'     => array('screenshot.jpg', 'screenshot.png', 'screenshot/*'), // 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的具体路径，例子： a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用)
            // 密钥的权限列表。简单上传和分片需要以下的权限，其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
            'allowActions'    => array(
                // 简单上传
                'name/cos:PutObject',
                'name/cos:PostObject',
                // 分片上传
                'name/cos:InitiateMultipartUpload',
                'name/cos:ListMultipartUploads',
                'name/cos:ListParts',
                'name/cos:UploadPart',
                'name/cos:CompleteMultipartUpload'
            ),
            // 临时密钥生效条件，关于condition的详细设置规则和COS支持的condition类型可以参考 https://cloud.tencent.com/document/product/436/71306
            "condition"       => array(
                "ip_equal" => array(
                    "qcs:ip" => array(
                        "10.217.182.3/24",
                        "111.21.33.72/24",
                    )
                )
            )
        );

        // 获取临时密钥，计算签名
        $tempKeys = $sts->getTempKeys($config);
        $redis->set($key, json_encode($tempKeys), 1800);
        return api_message($tempKeys);
    }

}
